﻿#include "NosepieceOlympusMX63.h"
#include <QTextStream>

namespace Qly
{

NosepieceOlympusMX63::NosepieceOlympusMX63(QObject *parent)
    : NosepieceInterface(parent),
      m_comPort("COM3"),
      m_baudRate(QSerialPort::Baud19200),
      m_dataBits(QSerialPort::Data8),
      m_parity(QSerialPort::EvenParity),
      m_stopBits(QSerialPort::TwoStop),
      m_serialPort(nullptr)
{

}

NosepieceOlympusMX63::~NosepieceOlympusMX63()
{
    cmd("1L 0\r\n");
    m_serialPort->close();
    delete m_serialPort;
}

void NosepieceOlympusMX63::setModelType(NosepieceOlympusMX63::ModelType model)
{
    m_type = model;
    switch (model)
    {
    case NosepieceOlympusMX63::D6RES:
    case NosepieceOlympusMX63::D6REMC:
    case NosepieceOlympusMX63::D6BDREMC:
        m_maxLens = 6;
        break;
    case NosepieceOlympusMX63::U5RES_ESD:
    case NosepieceOlympusMX63::D5BDREMC:
        m_maxLens = 5;
        break;
    }
    if(m_lensIndex >= m_maxLens) // lensIndex 从 0 到 n-1, 所以不能等于 maxLens
    {
        m_lensIndex = -1;// -1 表示当前物镜位置未知
    }
}

void NosepieceOlympusMX63::login()
{
    if(m_serialPort)
    {
        m_serialPort->close();
        disconnect(m_serialPort);
        delete m_serialPort;
    }
    m_serialPort = new QSerialPort(m_comPort, this);

    connect(m_serialPort, &QSerialPort::readyRead, this, &NosepieceOlympusMX63::on_dataReady);
    if(m_serialPort->open(QIODevice::ReadWrite))
    {
        qDebug() << m_baudRate;
        qDebug() << m_dataBits;
        qDebug() << m_parity;
        qDebug() << m_stopBits;
        m_serialPort->setBaudRate(m_baudRate);
        m_serialPort->setDataBits(static_cast<QSerialPort::DataBits> (m_dataBits));
        m_serialPort->setParity(static_cast<QSerialPort::Parity>(m_parity));
        m_serialPort->setStopBits(static_cast<QSerialPort::StopBits>(m_stopBits));
        m_serialPort->setFlowControl(QSerialPort::NoFlowControl);
        m_serialPort->clearError();
        m_serialPort->clear();


        cmd("1L 2\r\n"); // 切换到 remote 模式
        cmd("1SK1 1\r\n"); // 响应 MX63L 前面板按键
        cmd("1NOB 1\r\n"); // 物镜转动之后会回显位置数值
        cmd("1EILSW 1\r\n"); // 打开落射照明开关 , 0 表示关掉落射照明
        cmd("1VL 1\r\n"); // 响应 落射照明亮度调节旋钮，0 表示不响应
    }
    else
    {
        qWarning() << "open NosepieceOlympusMX63 Failed";
    }
}

void NosepieceOlympusMX63::showSetupDialog()
{

}

void NosepieceOlympusMX63::on_dataReady()
{
    QByteArray data = m_serialPort->readAll();
    //qDebug() << "NosepieceOlympusMX63::on_dataReady() : " << data;
    for(auto it = data.begin(); it != data.end(); ++it)
    {
        append(*it);
    }
}

void NosepieceOlympusMX63::loadSettings(QSettings &settings)
{
    qDebug() << "NosepieceOlympusMX63::loadSettings";
    m_comPort = settings.value("NosepieceCBFM/SerialPort", "COM1").toString();
    m_baudRate = settings.value("NosepieceCBFM/BaudRate", QSerialPort::Baud19200).toInt();
    m_dataBits = settings.value("NosepieceCBFM/DataBits", QSerialPort::Data8).toInt();
    m_parity = settings.value("NosepieceCBFM/Parity", QSerialPort::EvenParity).toInt();
    m_stopBits = settings.value("NosepieceCBFM/StopBits", QSerialPort::TwoStop).toInt();
    m_lensIndex = settings.value("NosepieceCBFM/Index", -1).toInt(); // -1 表示物镜位置未知

    login();
}

void NosepieceOlympusMX63::cmd(QString str)
{
    if(m_serialPort && m_serialPort->isWritable())
    {
        m_serialPort->write(str.toLocal8Bit());
        //QTextStream stream(m_serialPort);
        qDebug() << str;
        //stream << str;
        // if(!m_serialPort->waitForReadyRead(100))
        // {
        //     return;
        // }
        //QString ret = stream.readLine();
    }
}

void NosepieceOlympusMX63::append(char x)
{
    if(m_buffer.isEmpty())
    {
        if(x == '1')
        {
            m_buffer.append(x);
        }
        return;
    }
    else
    {
        m_buffer.append(x);
        if(x == '\n')
        {

            //到这里说明收到了一个完整的回复
            QString str(m_buffer);
            //qDebug() <<"received : " << str;
            if(str.startsWith("1L"))
            {
                responseL();
            }
            else if(str.startsWith("1NOB"))
            {
                responseNOB();
            }
            else if(str.startsWith("1SK"))
            {
                responseSK();
            }
            else if(str.startsWith("1NMU"))
            {
                responseNMU();
            }
            else if(str.startsWith("1OB"))
            {
                responseOB();
            }
            else if(str.startsWith("1VL"))
            {
                responseVL();
            }
            m_buffer.clear();
        }

    }
}

void NosepieceOlympusMX63::responseL()
{
	QString str(m_buffer);
	if(!str.contains("1L +"))
	{
        qWarning() << "switch to remote mode fail";
		//TODO 这里应该发出个信号，表示发生错误
	}
    return;
}

void NosepieceOlympusMX63::responseNOB()
{
    if(m_buffer.size() != 8)
    {
        return;
    }
	if(m_buffer.at(5) == '+') return;
	
    uint8_t c = m_buffer.at(5) - '1';// 换算为 0 开始的索引
    qDebug() << "in NOB: " << c << ", lensIndex = " << m_lensIndex;
    if( c >= 0 && c < m_maxLens )
    {
        if(m_lensIndex != c)
        {
            int oldLens = m_lensIndex;
            m_lensIndex= c;
            emit lensChanged(oldLens, m_lensIndex);
        }
    }

}

void NosepieceOlympusMX63::responseNMU()
{
    return;
}

void NosepieceOlympusMX63::responseSK()
{
    QString str(m_buffer);
    //qDebug() << "in NosepieceOlympusMX63::responseSK() : " << str << "lensIndex = " << m_lensIndex;
    if(str.contains("1SK1 5"))
    {
        forward();
    }
    else if(str.contains("1SK1 9"))
    {
        reverse();
    }
}

void NosepieceOlympusMX63::responseOB()
{
    QString str(m_buffer);
    return;
}

void NosepieceOlympusMX63::responseVL()
{
    QString str(m_buffer);
    str = str.mid(3);
    bool ok;
    int value = str.toInt(&ok);
    if(ok)
    {
        cmd("1EIL" + str);
    }
    return;
}

void NosepieceOlympusMX63::setLens(int lens)
{

    int lowerLimit = 0;
    int upperLimit = m_maxLens - 1;
    lens = qBound(lowerLimit, lens, upperLimit);
    cmd(QString("1OB %1\r\n").arg(lens + 1)); // Olympus 的物镜转盘是从 1 开始计数的。所以这里要 + 1
    // if(m_lensIndex != lens)
    // {
    //     m_lensIndex = lens;
    // }
}

void NosepieceOlympusMX63::setLens(int oldLens, int newLens)
{
    Q_UNUSED(oldLens);
    setLens(newLens);
}

void NosepieceOlympusMX63::forward()
{
    if(m_lensIndex < m_maxLens)
    {
        setLens(m_lensIndex + 1);
    }
    //m_nosepiece->dynamicCall("Forward()");
}

void NosepieceOlympusMX63::reverse()
{
    if(m_lensIndex > 0)
    {
        setLens(m_lensIndex - 1);
    }
    //m_nosepiece->dynamicCall("Reverse()");
}

void NosepieceOlympusMX63::writeSettings(QSettings &settings)
{
    settings.setValue("NosepieceCBFM/Index", m_lensIndex);
    cmd("1L 0\r\n"); // 这里还要再考虑考虑，写 settings 后是否要退出 remote 模式
    return;
}

}
